package com.ajun.common.rabbit;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.ExchangeBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMQ 绑定信息配置
 *
 * @author AJun
 * @date 2021-07-14
 */
@Configuration
public class RabbitBindConfig {

    /* 案例 */
    @Bean
    public FanoutExchange orderFanoutExchange() {
        return ExchangeBuilder.fanoutExchange(QueueConstants.ORDER_DISPATCH_FANOUT_EXCHANGE).durable(true).build();
    }

    @Bean
    public Queue orderQueue() {
        return QueueBuilder
            .durable(QueueConstants.ORDER_DISPATCH_QUEUE)
            // 绑定死信队列，消费异常的消息会被发到死信队列中
            .deadLetterExchange(QueueConstants.DLX_EXCHANGE)
            .deadLetterRoutingKey(QueueConstants.DLX_KEY) // fanout交换机不需要routingKey
            .build();
    }

    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue()).to(orderFanoutExchange());
    }

    /**
     * 交换机声明
     */
    /* fanout */
    @Bean
    public FanoutExchange fanoutExchange() {
        return ExchangeBuilder.fanoutExchange(QueueConstants.ORDER_FANOUT_EXCHANGE).durable(true).build();
    }

    /* direct */
    @Bean
    public DirectExchange directExchange() {
        return ExchangeBuilder.directExchange(QueueConstants.ORDER_DIRECT_EXCHANGE).durable(true).build();
    }

    /* ttl queue */
    @Bean
    public DirectExchange ttlExchange() {
        return ExchangeBuilder.directExchange(QueueConstants.ORDER_TTL_EXCHANGE).durable(true).build();
    }

    /* ttl message */
    @Bean
    public DirectExchange ttlMsgExchange() {
        return ExchangeBuilder.directExchange(QueueConstants.ORDER_TTL_MSG_EXCHANGE).durable(true).build();
    }

    /* dead letter exchange */
    @Bean
    public DirectExchange dlxExchange() {
        return ExchangeBuilder.directExchange(QueueConstants.DLX_EXCHANGE).durable(true).build();
    }

    /* dead letter exchange test */
    @Bean
    public DirectExchange dlxTestExchange() {
        return ExchangeBuilder.directExchange(QueueConstants.DLX_TEST_EXCHANGE).durable(true).build();
    }

    /**
     * 队列声明
     */
    /* fanout */
    @Bean
    public Queue smsFanoutQueue() {
        return QueueBuilder.durable(QueueConstants.SMS_FANOUT_QUEUE).build();
    }

    @Bean
    public Queue emailFanoutQueue() {
        return QueueBuilder.durable(QueueConstants.EMAIL_FANOUT_QUEUE).build();
    }

    @Bean
    public Queue noteFanoutQueue() {
        return QueueBuilder.durable(QueueConstants.NOTE_FANOUT_QUEUE).build();
    }

    /* direct */
    @Bean
    public Queue smsDirectQueue() {
        return QueueBuilder.durable(QueueConstants.SMS_DIRECT_QUEUE).build();
    }

    @Bean
    public Queue emailDirectQueue() {
        return QueueBuilder.durable(QueueConstants.EMAIL_DIRECT_QUEUE).build();
    }

    @Bean
    public Queue noteDirectQueue() {
        return QueueBuilder.durable(QueueConstants.NOTE_DIRECT_QUEUE).build();
    }

    /* ttl queue: 设置给队列表示该队列下所有消息都会在未消费后的指定时间后被丢弃 */
    @Bean
    public Queue smsTtlQueue() {
        // 发布到队列的消息在被丢弃之前可以存活多长时间（毫秒）
        // x-message-ttl 参数, int 类型, 单位: ms
        // 1.Java 原生设置参数
        // Queue queue = new Queue(QueueConstants.SMS_TTL_QUEUE);
        // queue.addArgument("x-message-ttl", 5000);

        // 2.Spring new Queue 设置参数
        // Map<String, Object> args = new HashMap<>();
        // args.put("x-message-ttl", 5000);
        // Queue queue = new Queue(QueueConstants.SMS_TTL_QUEUE, true, false, false, args);

        // 3.Spring Boot Amqp 简单化设置参数
        // Spring Boot Simple to set TTL.
        return QueueBuilder.durable(QueueConstants.SMS_TTL_QUEUE).ttl(5000).build();
    }

    @Bean
    public Queue emailTtlQueue() {
        return QueueBuilder.durable(QueueConstants.EMAIL_TTL_QUEUE).ttl(5000).build();
    }

    @Bean
    public Queue noteTtlQueue() {
        return QueueBuilder.durable(QueueConstants.NOTE_TTL_QUEUE).ttl(5000).build();
    }

    /* ttl message: 不在队列设置 ttl */
    @Bean
    public Queue smsTtlMsgQueue() {
        return QueueBuilder.durable(QueueConstants.SMS_TTL_MSG_QUEUE).build();
    }

    @Bean
    public Queue emailTtlMsgQueue() {
        return QueueBuilder.durable(QueueConstants.EMAIL_TTL_MSG_QUEUE).build();
    }

    @Bean
    public Queue noteTtlMsgQueue() {
        return QueueBuilder.durable(QueueConstants.NOTE_TTL_MSG_QUEUE).build();
    }

    /* dlx */
    @Bean
    public Queue dlxQueue() {
        return QueueBuilder.durable(QueueConstants.DLX_QUEUE).build();
    }

    /* dlx test */
    @Bean
    public Queue dlxTestQueue() {
        return QueueBuilder
            .durable(QueueConstants.DLX_TEST_QUEUE)
            .ttl(5000)
            // 绑定死信队列,超时后消息会进入死信队列
            .deadLetterExchange(QueueConstants.DLX_EXCHANGE)
            .deadLetterRoutingKey(QueueConstants.DLX_KEY)
            .build();
    }

    /**
     * 绑定键声明
     */
    /* fanout */
    @Bean
    public Binding smsFanoutBinding() {
        return BindingBuilder.bind(smsFanoutQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding emailFanoutBinding() {
        return BindingBuilder.bind(emailFanoutQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding noteFanoutBinding() {
        return BindingBuilder.bind(noteFanoutQueue()).to(fanoutExchange());
    }

    /* direct */
    @Bean
    public Binding smsDirectBinding() {
        return BindingBuilder.bind(smsDirectQueue()).to(directExchange()).with(QueueConstants.SMS_DIRECT_KEY);
    }

    @Bean
    public Binding emailDirectBinding() {
        return BindingBuilder.bind(emailDirectQueue()).to(directExchange()).with(QueueConstants.EMAIL_DIRECT_KEY);
    }

    @Bean
    public Binding noteDirectBinding() {
        return BindingBuilder.bind(noteDirectQueue()).to(directExchange()).with(QueueConstants.NOTE_DIRECT_KEY);
    }

    /* ttl queue */
    @Bean
    public Binding smsTtlBinding() {
        return BindingBuilder.bind(smsTtlQueue()).to(ttlExchange()).with(QueueConstants.SMS_TTL_KEY);
    }

    @Bean
    public Binding emailTtlBinding() {
        return BindingBuilder.bind(emailTtlQueue()).to(ttlExchange()).with(QueueConstants.EMAIL_TTL_KEY);
    }

    @Bean
    public Binding noteTtlBinding() {
        return BindingBuilder.bind(noteTtlQueue()).to(ttlExchange()).with(QueueConstants.NOTE_TTL_KEY);
    }

    /* ttl msg */
    @Bean
    public Binding smsTtlMsgBinding() {
        return BindingBuilder.bind(smsTtlMsgQueue()).to(ttlMsgExchange()).with(QueueConstants.SMS_TTL_MSG_KEY);
    }

    @Bean
    public Binding emailTtlMsgBinding() {
        return BindingBuilder.bind(emailTtlMsgQueue()).to(ttlMsgExchange()).with(QueueConstants.EMAIL_TTL_MSG_KEY);
    }

    @Bean
    public Binding noteTtlMsgBinding() {
        return BindingBuilder.bind(noteTtlMsgQueue()).to(ttlMsgExchange()).with(QueueConstants.NOTE_TTL_MSG_KEY);
    }

    /* dlx */
    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with(QueueConstants.DLX_KEY);
    }

    @Bean
    public Binding dlxTestBinding() {
        return BindingBuilder.bind(dlxTestQueue()).to(dlxTestExchange()).with(QueueConstants.DLX_TEST_KEY);
    }
}
